#include <Arduino.h>
#include "drv_i2c_bus.h"
#include "drv_oled.h"
#include "oled_data.h"
#include "config.h"

#define OLED_I2C_ADDR   0x3c//(0x78 >> 1)
#define	OP_Command 0x00
#define	OP_Data 0x40

#define OLED_X_SIZE		128
#define OLED_Y_SIZE		64
#define OLED_RAM_SIZE	1024

uint8_t *OLED_GRAM = NULL;
// uint8_t OLED_GRAM[8][128];
extern int oled_display_off_flag;
unsigned long ten_min=0;
extern volatile bool nightled_flag;

bool oled_write_cmd(uint8_t cmd)
{
	//bool iError = false;
	uint8_t buf[2];
	
	buf[0] = OP_Command;
	buf[1] = cmd;
	
	drv_i2c_write(OLED_I2C_ADDR, buf, sizeof(buf));

	return true;
}

bool oled_write_cmds(uint8_t *cmd, uint16_t cmd_len)
{
	uint8_t buf[1+cmd_len];
	
	buf[0] = OP_Command;
	memcpy(buf+1, cmd, cmd_len);
	
	drv_i2c_write(OLED_I2C_ADDR, buf, sizeof(buf));

	return true;
}

bool oled_write_data_len(uint8_t *data, uint16_t len)
{
	uint8_t buf[1+len];

	buf[0] = OP_Data;
	memcpy(buf+1, data, len);
	drv_i2c_write(OLED_I2C_ADDR, buf, len+1);

	return true;
}

bool oled_write_data(uint8_t data)
{
	//bool iError = false;
	uint8_t buf[2];
	
	buf[0] = OP_Data;
	buf[1] = data;

	drv_i2c_write(OLED_I2C_ADDR, buf, sizeof(buf));

	return true;
}

void oled_init(void)
{
	pinMode(23, OUTPUT);
	digitalWrite(23, 1);
	delay(10);
	digitalWrite(23, 0);
	delay(10);
	digitalWrite(23, 1);
    delay(10);
    oled_write_cmd(0xAE); /*display off*/

    oled_write_cmd(0x00); /*set lower column address*/
    oled_write_cmd(0x10); /*set higher column address*/

    oled_write_cmd(0x40); /*set display start line*/

    oled_write_cmd(0xB0); /*set page address*/

    oled_write_cmd(0x81); /*contract control*/
    oled_write_cmd(0x00); /*128*/

    oled_write_cmd(0xA0); /*set segment remap*///a1

    oled_write_cmd(0xA4);

    oled_write_cmd(0xA6); /*normal / reverse*/

    oled_write_cmd(0xA8); /*multiplex ratio*/
    oled_write_cmd(0x3F); /*duty = 1/64*/

    oled_write_cmd(0xC0); /*Com scan direction*///c8

    oled_write_cmd(0xD3); /*set display offset*/
    oled_write_cmd(0x00);

    oled_write_cmd(0xD5); /*set osc division*/
    oled_write_cmd(0x90);

    oled_write_cmd(0xD9); /*set pre-charge period*/
    oled_write_cmd(0x22);

    oled_write_cmd(0xDA); /*set COM pins*/
    oled_write_cmd(0x12);

    oled_write_cmd(0xdb); /*set vcomh*/
    oled_write_cmd(0x30);

    oled_write_cmd(0x8d); /*set charge pump enable*/
    oled_write_cmd(0x14);

	oled_clear();

	delay(100);

    oled_write_cmd(0xAF); /*display ON*/

    delay(100);

    // delay(100);
	// oled_clear();
    //oled_full();
    // oled_show_pic(4,0,24,24, menustatus2424[0], 0);
    // oled_show_pic(36,0,24,24, menustatus2424[1], 0);
    // oled_show_pic(68,0,24,24, menustatus2424[3], 0);
    // oled_show_pic(100,0,24,24, menustatus2424[8], 0);

	oled_malloc();

	oled_show_pic(36,0,50,64, orang, 0);  //开机图�?

    //OLED_DrawLine(0, 28, 4);
    
   // oled_show_string(32, 32, "12:35", 24, 0);
    oled_refresh();

	oled_free();
}

void oled_off(void)
{

  oled_write_cmd(0xAE); /*display off*/
  oled_clear();
}

void oled_display_off(void)
{
	oled_write_cmd(0xAE); /*display off*/
	oled_display_off_flag=1;
	//setRGB(0,0,0);
	nightled_flag=false;
}

/*
  flag  true  : display off no operation after 10 minutes
        false : display on always
*/
// void oled_display_on(bool flag)
// {
// 	oled_write_cmd(0xAF);
// 	oled_display_off_flag=0;
// 	if(flag)
// 	{
// 	  ten_min=millis();
// 	}
// 	else
// 	{
//       ten_min=0;
// 	}	
// }
 
// void  ten_min_off(void)
// {
// 	if(!oled_display_off_flag && ten_min)
// 	{
// 		if(millis()-ten_min==MINUTE*10)
// 		{
// 			oled_display_off();
// 		}
// 	}
// }

void oled_clear(void)
{
    uint8_t i;
    uint8_t data[128];
    uint8_t cmd[3];

    memset(data, 0x00, sizeof(data));

    for(i = 0; i < 8; i++)
    {
        // oled_write_cmd(0xb0+i);
        // oled_write_cmd(0x00);
        // oled_write_cmd(0x10);
        cmd[0] = 0xb0+i;
        cmd[1] = 0x01;
        cmd[2] = 0x10;
        oled_write_cmds(cmd, sizeof(cmd));
        oled_write_data_len(data, sizeof(data));
    }
}

void oled_full(void)
{
    uint8_t i;
    uint8_t data[128];
    // uint8_t cmd[3];

    memset(data, 0xff, sizeof(data));

    for(i = 0; i < 8; i++)
    {
        oled_write_cmd(0xb0+i);
        oled_write_cmd(0x00);
        oled_write_cmd(0x10);
        // cmd[0] = 0xb0+i;
        // cmd[1] = 0x01;
        // cmd[2] = 0x10;
        // oled_write_cmds(cmd, sizeof(cmd));
        oled_write_data_len(data, sizeof(data));
    }
}

//画点 
//x:0~127
//y:0~63
void OLED_DrawPoint(uint8_t x,uint8_t y)
{
	uint8_t i,m,n;
	uint16_t idx;

	i=y/8;
	m=y%8;
	n=1<<m;

	idx = i * OLED_X_SIZE + x;

	OLED_GRAM[idx] |= n;
}

//清除一�?�?
//x:0~127
//y:0~63
void OLED_ClearPoint(uint8_t x,uint8_t y)
{
	uint8_t i,m,n;
	uint16_t idx;

	if(OLED_GRAM == NULL)
	{
		return;
	}

	i=y/8;
	m=y%8;
	n=1<<m;

	idx = i * OLED_X_SIZE + x;
	OLED_GRAM[idx] = ~OLED_GRAM[idx];
	OLED_GRAM[idx] |= n;
	OLED_GRAM[idx] = ~OLED_GRAM[idx];
}

void oled_clear_ram(uint8_t x, uint8_t y, uint8_t x_len, uint8_t y_len)
{
	uint8_t i,j,cnt;
	uint16_t idx;

	if(OLED_GRAM == NULL)
	{
		return;
	}

	cnt=y_len/8;

	if((x+x_len) > 128)
	{
		x_len = 128 - x;
	}

	for(i = 0; i < cnt; i++)
	{
		for(j = x; j < (x+x_len); j++)
		{
			idx = (y/8+i) * OLED_X_SIZE + j;
			OLED_GRAM[idx] = 0;
		}
	}
}

//更新显存到OLED	
void oled_refresh(void)
{
	uint8_t i;//,n;

	if(OLED_GRAM == NULL)
	{
		return;
	}

	for(i = 0; i < 8; i++)
	{
	   oled_write_cmd(0xb0+i); //设置行起始地址
	   oled_write_cmd(0x00);   //设置低列起�?�地址
	   oled_write_cmd(0x10);   //设置高列起�?�地址
	   oled_write_data_len(&OLED_GRAM[i*OLED_X_SIZE], OLED_X_SIZE);
  }
}

void OLED_DrawLine(uint8_t x,uint8_t y, uint8_t interval)
{
	uint8_t x0;

    for(x0=x;x0<128;x0+=interval)
    {
        OLED_DrawPoint(x0, y);
    }
}

void oled_show_char(uint8_t x,uint8_t y,char chr,uint8_t size1)
{
	uint8_t i, m, temp, size2;
	uint8_t x0=x,y0=y;
	size2 = (size1/8+((size1%8)?1:0))*(size1/2);  //得到字体一�?字�?��?�应点阵集所占的字节�?
	
	uint16_t idx, len;

	len = strlen(asc2_2412_idx);
	
	for(idx = 0; idx < len; idx++)
	{
		if(chr == asc2_2412_idx[idx])
		{
			break;
		}
	}
	
	if(idx < len)
	{
		for(i=0;i<size2;i++)
		{
			if(size1==12)
			{
				return;//temp=asc2_1206[chr1][i];
			} //调用1206字体
			else if(size1==16)
			{
				return;//temp=asc2_1608[chr1][i];
			} //调用1608字体
			else if(size1==24)
			{
				temp = asc2_2412[idx][i];
			} //调用2412字体
			else 
				return;
			
			for(m=0;m<8;m++)           //写入数据
			{
				if(temp&0x01)OLED_DrawPoint(x0,y0);
				else OLED_ClearPoint(x0,y0);
				temp>>=1;
				y0++;
			}
			x0++;
			if((x0-x)==(size1/2))
			{
				x0=x; 
				y=y+8;
			}
			y0 = y;
		}
	}
}


void oled_show_string(uint8_t x, uint8_t y,const char *chr,uint8_t size1, uint8_t flag)
{
	while(*chr != '\0')
	{
		if((*chr>=' ')&&(*chr<='~'))//判断�?不是非法字�??!{ 	//ASCII
		{
			oled_show_char(x, y, *chr, size1);
			x += size1/2+4;
			if( x > (128-size1))  //换�??
			{
				x = 0;
				y += size1;
			}
			chr++;
		}
		else
		{
			// oled_show_chinese(x, y, chr, size1, flag);
			// x += size1+2;
			// if( x > (80-size1))  //换�??
			// {
			// 	x = 0;
			// 	y += size1;
			// }
			// chr++;
			// chr++;
		}
	}
}

void oled_show_pic(uint8_t x,uint8_t y, uint8_t xsize, uint8_t ysize, const uint8_t *pic, uint8_t flag)
{
	uint8_t m,x0=x,y0=y,temp;
	uint16_t i, size = (xsize * ysize) / 8;
	
	for(i = 0; i < size; i++)
	{
		temp = *(pic+i);
		for(m = 0; m < 8;m++)
		{
			if(flag == 0)
			{
				if(temp & 0x01)
					OLED_DrawPoint(x0,y0);
				else
					OLED_ClearPoint(x0,y0);
			}
			else
			{
				if(temp & 0x01)
					OLED_ClearPoint(x0,y0);
				else
					OLED_DrawPoint(x0,y0);
			}
			temp>>=1;
			y0++;
		}
		x0++;
		if((x0-x)==xsize)
		{
			x0=x;
			y=y+8;
		}
		y0 = y;
	}
}

bool oled_malloc(void)
{
	if(OLED_GRAM != NULL)
	{
		return true;
	}

	OLED_GRAM = (uint8_t *)malloc(OLED_RAM_SIZE);
	if(OLED_GRAM != NULL)
	{
		memset(OLED_GRAM, 0, OLED_RAM_SIZE);
		return true;
	}
	return false;
}

void oled_free(void)
{
	if(OLED_GRAM == NULL)
	{
		return;
	}

	free(OLED_GRAM);
	OLED_GRAM = NULL;
}
